﻿using System;
using System.Diagnostics;
using System.IO;
using System.Net.Mail;
using System.Reflection;
using System.Windows;
using Microsoft.Practices.Prism.Commands;
using MyFramework.Common.Interfaces;
using MyFramework.Helpers;
using MyFramework.Shell.Views;

namespace MyFramework.Shell.ViewModels
{
    /// <summary>
    /// Exception handling view model.
    /// </summary>
    public class ExceptionHandlingViewModel : EmailNotificationViewModel
    {
        #region Fields

        /// <summary>
        /// The exception.
        /// </summary>
        private readonly Exception exception;

        /// <summary>
        /// The mail attachment.
        /// </summary>
        private readonly byte[] mailAttachment;

        /// <summary>
        /// More information text on exception.
        /// </summary>
        private string moreInformation;

        /// <summary>
        /// Indicates whether the 'more information' text is visible.
        /// </summary>
        private bool moreInformationVisibility;

        /// <summary>
        /// The executable arguments
        /// </summary>
        private readonly string executableArguments;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ExceptionHandlingViewModel" /> class.
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="mailAttachment">The mail attachment.</param>
        /// <param name="executableArguments">The executable arguments.</param>
        public ExceptionHandlingViewModel(Exception exception, byte[] mailAttachment = null, string executableArguments = null)
        {
            this.exception = exception;
            this.mailAttachment = mailAttachment;
            this.executableArguments = executableArguments;
            this.RestartApplication = true;
            this.UserMessage = string.Empty;

            ExceptionDescriptor ed = new ExceptionDescriptor();
            this.moreInformation = ed.GetExceptionDescription(this.exception);

            this.SendCommand = new DelegateCommand(this.Send, this.CanSend);
            this.CloseCommand = new DelegateCommand(this.Close, this.CanClose);
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the more information.
        /// </summary>
        /// <value>
        /// The more information.
        /// </value>
        public string MoreInformation
        {
            get
            {
                return this.moreInformation;
            }
        }

        /// <summary>
        /// Gets the name of the application.
        /// </summary>
        /// <value>
        /// The name of the application.
        /// </value>
        public string ApplicationName
        {
            get
            {
                Type at = typeof(AssemblyTitleAttribute);
                Object[] r = Assembly.GetEntryAssembly().GetCustomAttributes(at, false);
                AssemblyTitleAttribute ta = (AssemblyTitleAttribute)(r[0]);
                return ta.Title;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [restart application].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [restart application]; otherwise, <c>false</c>.
        /// </value>
        public bool RestartApplication { get; set; }

        /// <summary>
        /// Gets or sets the user message.
        /// </summary>
        /// <value>
        /// The user message.
        /// </value>
        public string UserMessage { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether [more information visibility].
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [more information visibility]; otherwise, <c>false</c>.
        /// </value>
        public bool MoreInformationVisibility
        {
            get { return moreInformationVisibility; }
            set
            {
                if (value != moreInformationVisibility)
                {
                    moreInformationVisibility = value;
                    RaisePropertyChangedEvent(() => this.MoreInformationVisibility);
                }
            }
        }

        /// <summary>
        /// Gets or sets the send command.
        /// </summary>
        /// <value>
        /// The send command.
        /// </value>
        public DelegateCommand SendCommand { get; set; }

        /// <summary>
        /// Gets or sets the close command.
        /// </summary>
        /// <value>
        /// The close command.
        /// </value>
        public DelegateCommand CloseCommand { get; set; }

        #endregion

        #region Methods

        /// <summary>
        /// Closes this instance.
        /// </summary>
        protected virtual void Close()
        {
            if (this.RestartApplication)
            {
                string executable = Process.GetCurrentProcess().MainModule.FileName;
                if (string.IsNullOrEmpty(this.executableArguments))
                {
                    Process.Start(executable);
                }
                else
                {
                    Process.Start(executable, this.executableArguments);
                }
            }

            Environment.Exit(-1);
        }

        /// <summary>
        /// Determines whether this instance can close.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance can close; otherwise, <c>false</c>.
        /// </returns>
        protected virtual bool CanClose()
        {
            return true;
        }

        /// <summary>
        /// Determines whether this instance can send.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance can send; otherwise, <c>false</c>.
        /// </returns>
        protected virtual bool CanSend()
        {
            return true;
        }

        /// <summary>
        /// Sends this instance.
        /// </summary>
        protected virtual void Send()
        {
            try
            {
                using (MailMessage msg = new MailMessage())
                {
                    msg.IsBodyHtml = true;
                    msg.From = new MailAddress("info@satimax.it", "info");

                    msg.To.Add("digiulio.massimo@gmail.com");
                    msg.Subject = "Errore applicazione";
                    string template = ReadTemplate("MyFramework.Shell.Resources.ExceptionEmailTemplate.htm");
                    template = PatchTemplate(template);

                    msg.Body = string.Format(template, Process.GetCurrentProcess().ProcessName, ExceptionHelper.GetUserIdentity(), FormatHtml((string)this.UserMessage), this.MoreInformation.Trim().Replace(Environment.NewLine, "<br>"));

                    SmtpClient theClient = new SmtpClient("smtp.gmail.com", 587);
                    theClient.UseDefaultCredentials = false;
                    theClient.EnableSsl = true;
                    System.Net.NetworkCredential theCredential = new System.Net.NetworkCredential("assistenza.clienti.105@gmail.com", "ass1st3nz@");
                    theClient.Credentials = theCredential;

                    if (this.mailAttachment != null && this.mailAttachment.Length > 0)
                    {
                        using (MemoryStream ms = new MemoryStream(this.mailAttachment))
                        {
                            if (this.mailAttachment != null)
                            {
                                msg.Attachments.Add(new Attachment(ms, "Screenshot.jpg"));
                            }
                            theClient.Send(msg);

                        }
                    }
                    else
                    {
                        theClient.Send(msg);
                    }

                }
            }
            catch (Exception e1)
            {
                MessageBox.Show(e1.Message, e1.StackTrace, MessageBoxButton.OK, MessageBoxImage.Error);
            }


            this.Close();
        }

        /// <summary>
        /// Gets the main view.
        /// </summary>
        /// <returns></returns>
        /// <value>
        /// The main view.
        ///   </value>
        public override IView GetMainView()
        {
            return new ExceptionHandlingView();
        }

        #endregion
    }
}
